package com.chuxing.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chuxing.config.ExamState;
import com.chuxing.domain.ClassInfo;
import com.chuxing.domain.DTO.InterviewListDTO;
import com.chuxing.domain.Interview;
import com.chuxing.domain.TClassMembers;
import com.chuxing.domain.User;
import com.chuxing.domain.VO.PageResultVO;
import com.chuxing.exception.GenericException;
import com.chuxing.exception.UnauthorizedException;
import com.chuxing.security.mapper.UserMapper;
import com.chuxing.system.mapper.InterviewMapper;
import com.chuxing.system.mapper.TClassMembersMapper;
import com.chuxing.system.service.IClassinfoService;
import com.chuxing.system.service.IInterviewService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * 面试信息Service业务层处理
 * 
 * @author 刘祺
 * @date 2024-12-10
 */
@Service
@RequiredArgsConstructor
@Transactional
@Slf4j
public class InterviewServiceImpl extends ServiceImpl<InterviewMapper, Interview> implements IInterviewService
{
    private final InterviewMapper interviewMapper;

    private final UserMapper userMapper;

    private final TClassMembersMapper tClassMembersMapper;

    private final IClassinfoService classinfoService;


    /**
     * 查询面试信息
     * 
     * @param intvId 面试信息主键
     * @return 面试信息
     */
    @Override
    public Interview selectInterviewByIntvId(Long intvId)
    {
        return interviewMapper.selectInterviewByIntvId(intvId);
    }

    /**
     * 查询面试信息列表
     * 
     * @param interviewListDTO 面试信息
     * @return 面试信息
     */
    @Override
    public PageResultVO selectInterviewList(InterviewListDTO interviewListDTO)
    {
        // 验证分页参数
        int pageNum = Math.max(1, interviewListDTO.getPageNum());
        int pageSize = Math.max(1, interviewListDTO.getPageSize());
        // 启用分页查询
        PageHelper.startPage(pageNum, pageSize);
        try {
            try (Page<Interview> page = interviewMapper.selectInterviewList(interviewListDTO)) {
                // 构造并返回分页结果对象
                return new PageResultVO(page.getTotal(), page.getResult());
            }
        } catch (Exception e) {
            // 抛出通用异常，不暴露具体错误信息
            throw new GenericException("系统内部错误");
        } finally {
            // 确保分页查询结束
            PageHelper.clearPage();
        }
    }

    /**
     * 新增面试信息
     * 
     * @param interview 面试信息
     * @return 结果
     */
    @Override
    @Caching(evict = {
            @CacheEvict(value = "tClassMembersCache", allEntries = true),
            @CacheEvict(value = "interviewCache", allEntries = true),
            @CacheEvict(value = "userInfo", allEntries = true)
    })
    public int insertInterview(Interview interview)
    {
        // 检查该学生是否已提交过面试信息
        Interview interview1 = interviewMapper.selectInterviewByStudentId(interview.getStudentId());
        if (interview1 != null) {
            throw new GenericException("该学生已提交过面试信息");
        }
        // 设置创建时间和更新时间为当前时间
        interview.setCreateTime(LocalDateTime.now());
        interview.setUpdateTime(LocalDateTime.now());
        // 判定成绩是否合法
        if (interview.getIntvScore() != null && (interview.getIntvScore() < 0 || interview.getIntvScore() > 100)) {
            throw new GenericException("成绩不合法");
        }
        // 判断面试分数是否通过
        if (interview.getIntvScore() != null) {
            if (interview.getIntvScore() >= 60) {
                interview.setIntvState(ExamState.EXAM_PASS);
            } else {
                interview.setIntvState(ExamState.EXAM_FAIL);
            }
        }
        // 如果面试状态为已通过，则更新用户信息和班级信息
        if ("已通过".equals(interview.getIntvState())) {
            // 根据学生ID获取用户信息
            User user = userMapper.selectByStudentId(interview.getStudentId());
            // 获取默认班级信息
            ClassInfo classInfo = classinfoService.selectClassinfoByIsDefault(1);
            // 如果用户和班级信息均存在，则更新用户的班级信息
            if (user != null && classInfo != null) {
                user.setClassID(classInfo.getId());
                userMapper.updateByStudentId(user);
            }
            // 创建新的学生记录并插入数据库
            TClassMembers tClassMembers = new TClassMembers();
            if(user!=null){
                BeanUtils.copyProperties(user, tClassMembers);
                tClassMembers.setUpdateTime(LocalDateTime.now());
                tClassMembers.setCreateTime(LocalDateTime.now());
                //查询学生记录
                List<TClassMembers> tClassMembersList = tClassMembersMapper.selectTClassByStudentId(user.getStudentId());
                //删除旧记录
                for (TClassMembers aClass : tClassMembersList) {
                    if(aClass.getClassID().equals(tClassMembers.getClassID())){
                        tClassMembersMapper.deleteTClassById(aClass.getId());
                    }
                }
                tClassMembersMapper.insertTClass(tClassMembers);
            }
        }
        // 插入面试信息到数据库
        return interviewMapper.insertInterview(interview);
    }

    /**
     * 修改面试信息
     * 
     * @param interview 面试信息
     * @return 结果
     */
    @Override
    @Caching(evict = {
            @CacheEvict(value = "tClassMembersCache", allEntries = true),
            @CacheEvict(value = "interviewCache", allEntries = true),
            @CacheEvict(value = "userInfo",allEntries = true)
    })
    public int updateInterview(Interview interview)
    {
        // 更新面试信息的更新时间
        interview.setUpdateTime(LocalDateTime.now());
        //判定成绩是否合法
        if (interview.getIntvScore() != null && (interview.getIntvScore() < 0 || interview.getIntvScore() > 100)) {
            throw new GenericException("成绩不合法");
        }
        // 如果面试状态为已通过，则更新用户信息和班级信息
        if (ExamState.EXAM_PASS.equals(interview.getIntvState())) {
            // 根据学生ID获取用户信息
            User user = userMapper.selectByStudentId(interview.getStudentId());
            // 获取默认班级信息
            ClassInfo classInfo = classinfoService.selectClassinfoByIsDefault(1);
            //如果默认班级信息不存在
            if (classInfo == null) {
                throw new GenericException("请先设置默认班级");
            }
            // 如果用户和班级信息均存在，则更新用户的班级信息
            if (user != null) {
                user.setClassID(classInfo.getId());
                userMapper.updateByStudentId(user);
            }
            // 创建新的学生记录并插入数据库
            TClassMembers tClassMembers = new TClassMembers();
            if(user!=null){
                BeanUtils.copyProperties(user, tClassMembers);
                tClassMembers.setUpdateTime(LocalDateTime.now());
                tClassMembers.setCreateTime(LocalDateTime.now());
                //查询学生记录
                List<TClassMembers> tClassMembersList = tClassMembersMapper.selectTClassByStudentId(user.getStudentId());
                //删除旧记录
                for (TClassMembers aClass : tClassMembersList) {
                    if(aClass.getClassID().equals(tClassMembers.getClassID())){
                        tClassMembersMapper.deleteTClassById(aClass.getId());
                    }
                }
                tClassMembersMapper.insertTClass(tClassMembers);
            }
        }
        // 调用面试信息 mapper 的更新方法
        return interviewMapper.updateInterview(interview);
    }

    /**
     * 批量删除面试信息
     * 
     * @param intvIds 需要删除的面试信息主键
     * @return 结果
     */
    @Override
    @CacheEvict(value = "interviewCache", allEntries = true)
    public int deleteInterviewByIntvIds(Long[] intvIds)
    {
        return interviewMapper.deleteInterviewByIntvIds(intvIds);
    }

    /**
     * 获取面试信息
     *
     * 此方法用于获取当前登录学生的面试信息它首先检查用户是否已登录，
     * 如果未登录，则抛出UnauthorizedException异常如果用户已登录，
     * 它将根据登录用户的ID查询并返回相应的面试信息
     *
     * @return Interview 返回面试信息对象
     * @throws UnauthorizedException 如果用户未登录，则抛出此异常
     */
    @Override
    @Cacheable(value = "interviewCache", key = "'studentId'+#studentId")
    public Interview getIntvInfo(String  studentId) {
        log.info("数据库查询面试信息{}", studentId);
        // 根据学生ID查询并返回面试信息
        return interviewMapper.selectInterviewByStudentId(studentId);
    }

    /**
     * 保存考试信息
     *
     * 此方法主要用于保存面试（考试）的相关信息到数据库中，在执行保存操作前，会进行登录状态的检查，
     * 以确保只有已登录的用户才能保存信息此外，方法还会更新面试信息的创建时间和更新时间，并根据学生ID
     * 删除已存在的面试记录，以避免重复保存
     *
     * @param interview 面试对象，包含需要保存的面试（考试）信息
     * @throws UnauthorizedException 如果用户未登录，则抛出此异常
     */
    @Override
    @CacheEvict(value = "interviewCache",allEntries = true)
    public void saveExamInfo(Interview interview) {
        // 设置面试信息的创建时间和更新时间为当前时间
        interview.setCreateTime(LocalDateTime.now());
        interview.setUpdateTime(LocalDateTime.now());
        // 设置面试信息的状态为未面试
        interview.setIntvState("未面试");
        // 设置考试分数为null
        interview.setIntvScore(null);
        // 删除已存在的该学生的面试记录，以防止重复保存
        interviewMapper.deletebyStudentId(interview.getStudentId());
        // 将新地面试信息插入数据库
        interviewMapper.insert(interview);
    }

    /**
     * 清除指定学生的面试缓存信息
     * 此方法使用Spring的CacheEvict注解，旨在学生信息更新后清除其对应的缓存数据
     * 这是为了确保后续对同一学生信息的请求能够重新生成并缓存最新的信息
     *
     * @param studentId 学生ID，用于标识和清除缓存中对应的学生信息
     */
    @Override
    @CacheEvict(value = "interviewCache", allEntries = true)
    public void clear(String studentId) {
        // 删除该学生已有的考试记录
        interviewMapper.deletebyStudentId(studentId);
    }

    @Override
    public void deleteAll() {
        interviewMapper.deleteAll();
    }

    @Override
    @Caching(evict = {
            @CacheEvict(value = "tClassMembersCache", allEntries = true),
            @CacheEvict(value = "interviewCache", allEntries = true),
            @CacheEvict(value = "userInfo",allEntries = true)
    })
    public void checkInterviewScoreLine(Integer score) {
        if(score==null){
            throw new GenericException("请输入分数线");
        }
        if(score<0||score>100){
            throw new GenericException("分数线不合法");
        }
        // 获取默认班级信息
        ClassInfo classInfo = classinfoService.selectClassinfoByIsDefault(1);
        //如果默认班级信息不存在
        if (classInfo == null) {
            throw new GenericException("请先设置默认班级");
        }
        //查询所有面试信息
        List<Interview> interviewList = interviewMapper.list();
        List<User> users = userMapper.list();
        HashMap<String, User> userHashMap = new HashMap<>();
        ArrayList<TClassMembers> tClassMembersList = new ArrayList<>();
        //创建用户哈希表
        for (User user : users) {
            userHashMap.put(user.getStudentId(),user);
        }
        for (Interview interview : interviewList) {
            if(interview.getIntvScore()>=score){
                interview.setIntvState(ExamState.EXAM_PASS);
                userHashMap.get(interview.getStudentId()).setClassID(classInfo.getId());
                TClassMembers tClassMembers = new TClassMembers();
                BeanUtils.copyProperties(userHashMap.get(interview.getStudentId()), tClassMembers);
                tClassMembers.setCreateTime(LocalDateTime.now());
                tClassMembers.setUpdateTime(LocalDateTime.now());
                tClassMembersList.add(tClassMembers);
            }else{
                interview.setIntvState(ExamState.EXAM_FAIL);
            }
        }
        //清空数据库
        interviewMapper.deleteAll();
        //插入数据库
        if(!interviewList.isEmpty()){
            interviewMapper.insert(interviewList);
        }
        //根据卓越班编号查询班级学生
        List<TClassMembers> classMembers = tClassMembersMapper.selectListByClassID(classInfo.getId());
        //对比tClassMembersList和classMembers将学号相同的数据整理成一个集合
        ArrayList<Long> deleteClassMembers = new ArrayList<>();
        for (TClassMembers classMember : classMembers) {
            for (TClassMembers tClassMembers : tClassMembersList) {
                if (classMember.getStudentId().equals(tClassMembers.getStudentId())) {
                    deleteClassMembers.add(classMember.getId());
                }
            }
        }

        if(!deleteClassMembers.isEmpty()){
            tClassMembersMapper.deleteByIds(deleteClassMembers);
        }
        if( !tClassMembersList.isEmpty()){
            tClassMembersMapper.inserts(tClassMembersList);
        }
        //统一修改tClassMembersList中学生的账号的classID为默认班级id
        ArrayList<String> studentIds = new ArrayList<>();
        for (TClassMembers tClassMembers : tClassMembersList) {
            studentIds.add(tClassMembers.getStudentId());
        }
        if (!studentIds.isEmpty()) {
            userMapper.updateClassIDByStudentIds(studentIds, classInfo.getId());
        }
    }
}
